classdef FisherScore < Algorithm & Metric
    %FISHERSCORE Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
    end
    
    methods
        function [ this ] = FisherScore( name )
            if nargin == 0
                this.setName('fisher_score');
            end
            if nargin >= 1
                this.setName(name);
            end
        end
    end
    
    methods
        function [ z_result ] = apply( this, X, Y )
            z_result = this.calc(X, Y);
        end
    end
    
    methods ( Static = true )
        function [ z_result ] = calc( X, Y )
            nLabel = size(Y, 2);
            z_result = zeros(1, nLabel);
            for iLabel = 1:nLabel
                z_result(iLabel) = calcFisherScore(X, Y(:, iLabel));
            end
        end
    end
    
end

function [ result ] = calcFisherScore( X, Y )

z_id_1 = Y == 1;
z_id_2 = Y ~= 1;

nObs1 = nnz(z_id_1);
nObs2 = nnz(z_id_2);

if nObs1 == 0 || nObs2 == 0
    error('');
end

X1 = X(z_id_1, :);
X2 = X(z_id_2, :);
X1_mean = mean(X1, 1);
X2_mean = mean(X2, 1);
X1_centered = bsxfun(@minus, X1, X1_mean);
X2_centered = bsxfun(@minus, X2, X2_mean);
S1 = X1_centered'*X1_centered;
S2 = X2_centered'*X2_centered;

% if size(X, 2) == 1
%     result = sum((X1_mean - X2_mean).^2)/(var(X1) + var(X2));
%     return
% end

S_w = S1 + S2;

X_mean_diff = X1_mean - X2_mean;
S_b = X_mean_diff'*X_mean_diff;

[~, lambda] = eigs(S_b, S_w, 1, 'lm', struct('disp', 0));
result = abs(lambda);

end
